package com.gjy.spring.boot4;

import com.gjy.spring.boot.HelloBeanA;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.*;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;

import java.util.List;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-12-18 13:25:33
 */
public class BootAuto1 {

    public static void main(String[] args) {

        GenericApplicationContext app = new GenericApplicationContext();
        app.getDefaultListableBeanFactory().setAllowBeanDefinitionOverriding(true); // 是否允许覆盖
        app.registerBean("config", Config.class);
        app.registerBean(ConfigurationClassPostProcessor.class);
        app.refresh(); // 必加，不然配置类不会被加载

        for (String s : app.getBeanDefinitionNames()) {
            System.out.println(s);
        }
    }

    @Configuration
    //@Import({A1.class, A2.class}) // 加载配置类
    @Import({MyImportSelector.class})
    static class Config {
        // 如果有两个对象相同，默认会选择本配置类的
        // 原因：Import先解析，再加载本配置类。Bean工厂默认可以后注册的Bean覆盖前注册的Bean,可以使用setAllowBeanDefinitionOverriding设置为false，不能覆盖。
    }

    // 如果实现的接口是DeferredImportSelector,则会优先解析本项目的在解析Import的
    static class MyImportSelector implements ImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata metadata) {
            //return new String[]{A1.class.getName(), A2.class.getName()};
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            for (String name : SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, null)) {
                System.out.println(name);
            }
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            List<String> list = SpringFactoriesLoader.loadFactoryNames(MyImportSelector.class, null);
            return list.toArray(new String[0]);
        }
    }

    @Configuration
    static class A1 {
        @Bean
        @ConditionalOnMissingBean
        public HelloBeanA h1() {
            return new HelloBeanA();
        }
    }

    @Configuration
    static class A2 {
        @Bean
        public HelloBeanA h2() {
            return new HelloBeanA();
        }
    }
}
